<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
  <title>Limb3 JS Tests</title>
  <meta http-equiv="content-type" content="text/html; charset=utf-8" />
  <script src="../lib/prototype.js" type="text/javascript"></script>
  <script src="../lib/unittest.js" type="text/javascript"></script>

  <script src="../../shared/limb.js" type="text/javascript"></script>

  <link rel="stylesheet" href="../test.css" type="text/css" />
</head>
<body>
<h1>Limb.Classkit test</h1>

<!-- Log output -->
<div id="testlog"> </div>

<!-- Tests follow -->
<script type="text/javascript" language="javascript" charset="utf-8">
// <![CDATA[

new Test.Unit.Runner({
  tearDown: function()
  {
    if(MyIterface)
    {
      delete MyIterface;
      MyIterface = null;
    }

    if(MyParentClass)
    {
      delete MyParentClass;
      MyParentClass = null;
    }

    if(MyClass)
    {
      delete MyClass;
      MyClass = null;
    }
  },

  testCreateEmptyClass: function()
  {
    var test_class = Limb.Class('MyClass');

    this.assert(typeof(test_class) == 'function', 'Limb.Class returns object which is not class');
    this.assert(typeof(MyClass) == 'function', 'Object defined by Limb.Class is not class');

    var test_object = new MyClass();
    this.assert(typeof(test_object.__construct) == 'function', 'Defined class have not __construct method');
  },

  testCreateClassWithPrototype: function()
  {
    Limb.Class('MyClass',
    {
      returnFive: function() { return 5; }
    });


    var test_object = new MyClass();
    this.assert(typeof(test_object.returnFive) == 'function', 'Object prototype not extended');
    this.assertEqual(test_object.returnFive(), 5, 'Object prototype not extended');
  },

  testCreateInterface: function()
  {
    var test_interface = Limb.Interface('MyIterface');

    this.assert(typeof(test_interface) == 'function', 'Limb.Class returns interface which is not function');
    this.assert(typeof(MyIterface) == 'function', 'Object defined by lmbIterface is not function');
    this.assert(MyIterface.is_interface, 'is_interface not defined');
  },

  testFailedToCreateInstanceOfInterface: function()
  {
    var test_interface = Limb.Interface('MyIterface');

    try
    {
      var test_interface = new MyIterface();
      this.assert(false, 'Creation interface instance not throws exception');
    }
    catch(error)
    {
      this.assertEqual('InterfaceException', error.getType(), 'Exception type wrong');
      this.assertEqual('Can not create instance of interface', error.getMessage(), 'Exception message wrong');
    }
  },

  testFillInterfaceByStubMethods: function()
  {
    var test_interface = Limb.Interface('MyIterface',
    {
      testMethod: function() {}
    });

    this.assert(typeof(MyIterface.testMethod) == 'function', 'Interface not extended');

    try
    {
      MyIterface.testMethod();
      this.assert(false, 'Call interface method not throws exception');
    }
    catch(error)
    {
      this.assertEqual('InterfaceException', error.getType(), 'Exception type wrong');
      this.assertEqual('Interface methods can not be called', error.getMessage(), 'Exception message wrong');
    }
  },

  testClassStaticMethodDefinition: function()
  {
    Limb.Class('MyClass',
    {
      static: {
        returnFive: function() { return 5; }
      }
    });

    var test_object = new MyClass();
    this.assert(typeof(test_object.returnFive) == 'undefined', 'Static method is defined in prototype');
    this.assert(typeof(MyClass.returnFive) == 'function', 'Static method not added to class');
    this.assertEqual(MyClass.returnFive(), 5, 'Static method not added to class');
  },

  testClassStaticProperty: function()
  {
    Limb.Class('MyClass',
    {
      returnFiveInstance: function() { return this.static.returnFive(); },

      static: {
        returnFive: function() { return 5; }
      }
    });

    var test_object = new MyClass();
    this.assert(Limb.isset(test_object.static), 'Static property is not defined');
    this.assertEqual(5, test_object.returnFiveInstance(), 'Static property not refer to class');
  },

  testInheritance: function()
  {
    Limb.Class('MyParentClass',
    {
      setNumber: function(number) { this.number = number; }
    });

    Limb.Class('MyClass',
    {
      returnFive: function() { this.parent.setNumber(5); return this.number; }
    });

    Limb.Classkit.inherit(MyClass, MyParentClass);

    var test_object = new MyClass();
    this.assertEqual('MyClass', test_object.NAME, 'NAME attribute clones too');
    this.assertEqual(5, test_object.returnFive(), 'Parent method works with another this reference');
  },

  testClassToString: function()
  {
    Limb.Class('MyClass');
    this.assertEqual('[ class MyClass ]', MyClass.toString());
  },

  testInterfaceToString: function()
  {
    Limb.Interface('MyInterface');
    this.assertEqual('[ interface MyInterface ]', MyInterface.toString());
  }
});

// ]]>
</script>
</body>
</html>